const {
	isEmpty
} = require("./util");
const {
	ENUM_VALIDATOR_RULE,
	ENUM_VALIDATOR_TYPE
} = require("./enum_utils.js");
/** 校验策略 */
const validatorStrategies = {
	[`${ENUM_VALIDATOR_RULE.IS_NOT_EMPTY}`]: isNotEmpty,
	[`${ENUM_VALIDATOR_RULE.IS_MOBILE}`]: isMobile,
	[`${ENUM_VALIDATOR_RULE.IS_LAND_LINE}`]: isLandLine,
	[`${ENUM_VALIDATOR_RULE.IS_ID_CARD}`]: isIDCard,
	[`${ENUM_VALIDATOR_RULE.MIN_LENGTH}`]: minLength,
	[`${ENUM_VALIDATOR_RULE.MAX_LENGTH}`]: maxLength,
	[`${ENUM_VALIDATOR_RULE.IS_SAFE_PASSWORD}`]: isSafePassword,
	[`${ENUM_VALIDATOR_RULE.IS_NUMBER}`]: isNumber,
	[`${ENUM_VALIDATOR_RULE.IS_STRING}`]: isString,
	[`${ENUM_VALIDATOR_RULE.IS_ENCHAR}`]: isENChar,
	[`${ENUM_VALIDATOR_RULE.IS_NULL}`]: isNull,
}
// 校验是否为空
function isNotEmpty(checkData, errorMsg = '不能为空') {
	if (isEmpty(checkData)) return errorMsg;
}
// 校验是否为 null
function isNull(checkData, errorMsg = '数据为空') {
	if (isEmpty(checkData, true)) return errorMsg;
}
/** 校验是否是string */
function isString(checkData, errorMsg = '非字符串') {
	if (typeof checkData == 'string') return errorMsg;
}
/** 校验是否是数字 */
function isNumber(checkData, errorMsg = '非数字') {
	const regex = /^[0-9]+.?[0-9]*$/;
	if (!regex.test(checkData)) return errorMsg
}
/** 校验是否是英文字符 */
function isENChar(checkData, errorMsg = '非英文字符') {
	const regex = /^[A-Za-z]+$/;
	if (!regex.test(checkData)) return errorMsg;
}
/** 校验密码安全 */ // 字符开头 字符+数字+下划线 6 - 18位
function isSafePassword(checkData, errorMsg = '密码不安全') {
	// /^\w+$/ 数字、字符、下划线 
	const regex = /^[a-zA-Z]\w{5,17}$/
	if (!regex.test(checkData)) return errorMsg;
}
/** 校验数据最小长度 */
function minLength(checkData, length = 0, errorMsg = '超出最小长度') {
	if (checkData.length < length) return errorMsg;
}
/** 校验数据最大长度 */
function maxLength(checkData, length, errorMsg = '超出最大长度') {
	if (checkData.length > length) return errorMsg;
}
// 校验座机
function isLandLine(checkData, errorMsg = '错误的座机号码') {
	const regex = /^(\d{3,4}-)?\d{7,8}$/
	if (!regex.test(checkData)) return errorMsg;
}
// 校验手机
function isMobile(checkData, errorMsg = '错误的手机号码') {
	const regex = /^1[3|4|5|6|7|8|9][0-9]{9}$/;
	if (!regex.test(checkData)) return errorMsg;
}
// 校验身份证
function isIDCard(checkData, errorMsg = '错误的身份证号码') {
	const regex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
	if (!regex.test(checkData)) return errorMsg;
}

/** =====================校验对象===================== */
let Validator = function() {
	this.cache = []; // 校验规则缓存
	this.validatorType = ENUM_VALIDATOR_TYPE.OR; // 整体校验规则： or 或（只有一个失败就抛出）| and 且（全部错误就抛出）
}
/**
 * 校验对象添加校验规则
 * @param {any} checkData 要检查的数据
 * @param {string} rule 校验规则---校验策略名 或者 校验策略名:校验限制参数（以：进行分割）
 * @param {string} errMsg 校验错误信息
 * @param {object} context 校验上下文，默认为null
 */
Validator.prototype.add = function(checkData, rule, errMsg, context = null) {
	let array = rule.split(":");
	this.cache.push(function() { // 使用空函数包装校验方法，并放入缓存
		var strategyKey = array.shift(); // 获取校验规则策略名称
		array.unshift(checkData); // 在首位插入要校验的数据
		if (errMsg) {
			array.push(errMsg) // 在末尾插入错误信息
		}
		return validatorStrategies[strategyKey].apply(context, array)
	})
}

/**
 * 触发校验
 */
Validator.prototype.start = function() {
	// 循环检验规则缓存
	let errMsgList = [];
	for (let i = 0; i < this.cache.length; i++) {
		let errMsg = this.cache[i](); // 开始执行缓存中的校验方法
		if (errMsg) { // 如果有返回值，校验没有通过， 抛出错误信息
			errMsgList.push(errMsg);
			if (this.validatorType == ENUM_VALIDATOR_TYPE.OR) return errMsg;
		}
	}
	if (this.validatorType == ENUM_VALIDATOR_TYPE.AND) {
		if (errMsgList && errMsgList.length == this.cache.length) { // 错误信息缓存长度 不等于 校验缓存长度， 有通过校验的内容
			return errMsgList[0];
		} else {
			return null;
		}
	}
	return null;
}

/**
 * 设置整体校验规则
 * @param {string} type // or 或（只有一个失败就抛出）and 且（全部错误就抛出）
 */
Validator.prototype.setValidatorType = function(type) {
	if (type != ENUM_VALIDATOR_TYPE.OR && type != ENUM_VALIDATOR_TYPE.AND) {
		type = ENUM_VALIDATOR_TYPE.OR
	}
	this.validatorType = type;
}

export default Validator;